package com.ddwl.gate.service;

import com.ddwl.common.constant.BaseEnum;
import com.ddwl.common.constant.GateEnum;
import com.ddwl.common.constant.RedisKey;
import com.ddwl.common.service.RedisService;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.UUIDGenerator;
import com.ddwl.gate.mapper.DictionaryMapper;
import com.ddwl.gate.model.Dictionary;
import com.ddwl.schema.bo.base.PageBo;
import com.ddwl.schema.bo.gate.DictionaryBo;
import com.ddwl.schema.bo.gate.DictionarySearchBo;
import com.ddwl.schema.vo.base.PageVo;
import com.ddwl.schema.vo.gate.DictionaryVo;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * @author Fu Zhaohui
 * @version 1.0.0
 * @date 2019/8/28 17:17
 */
@Service
@RequiredArgsConstructor
public class DictionaryService {

    private final DictionaryMapper dictionaryMapper;
    private final RedisService redisService;

    public PageVo<DictionaryVo> page(PageBo<DictionarySearchBo> pageBo) {
        PageVo<DictionaryVo> pageVo = new PageVo<>();
        BeanUtils.copyProperties(pageBo, pageVo);
        pageVo.setSize(pageBo.getPageSize());
        PageHelper.startPage(pageBo.getPage(), pageBo.getPageSize());
        Dictionary params = BeanConverUtils.convertBean(pageBo.getParam(), Dictionary.class);
        Page<Dictionary> pageable = (Page<Dictionary>) dictionaryMapper.select(params);
        pageVo.setTotal(pageable.getTotal());
        pageVo.setData(pageable.getResult().stream().map(entity -> {
            DictionaryVo vo = new DictionaryVo();
            BeanUtils.copyProperties(entity, vo);
            return vo;
        }).collect(Collectors.toList()));
        return pageVo;
    }

    /**
     * 查询字段属性列表
     *
     * @param tag
     * @return
     */
    public List<DictionaryVo> getByFieldTag(String tag) {
        Dictionary params = new Dictionary();
        params.setFieldTag(tag);
        params.setStatus(BaseEnum.StatusEnum.ENABLE.getCode());
        List<Dictionary> entities = dictionaryMapper.select(params);
        List<DictionaryVo> dictionaryVos = new ArrayList<>();
        Map<String, List<DictionaryVo>> childrenMap = new TreeMap<>();
        entities.forEach(entity -> {
            DictionaryVo vo = new DictionaryVo();
            BeanUtils.copyProperties(entity, vo);
            Long pid = entity.getPid();
            if (pid == 0L) {
                List<DictionaryVo> children = new ArrayList<>();
                vo.setChildren(children);
                childrenMap.put(entity.getId(), children);
                dictionaryVos.add(vo);
            } else {
                childrenMap.get(pid).add(vo);
            }
        });
        return dictionaryVos;
    }

    public String getSettingVal(String tag, String field) {
        String fieldVal = redisService.getHashOps().get(RedisKey.DICTIONARY_KEY.getKey(tag), field);
        if (StringUtils.hasText(fieldVal)) {
            return fieldVal;
        }
        Dictionary params = new Dictionary();
        params.setFieldTag(tag);
        params.setFieldName(field);
        params.setStatus(BaseEnum.StatusEnum.ENABLE.getCode());
        Dictionary entity = dictionaryMapper.selectOne(params);
        if (entity == null) {
            try {
                GateEnum.DictionaryField dictionaryField = GateEnum.DictionaryField.valueOf(field);
                if (dictionaryField == null) {
                    return null;
                }
                return dictionaryField.getDefaultVal().toString();
            } catch (Exception e) {
                return null;
            }
        }
        return entity.getFieldVal();
    }

    /**
     * 获取Tag配置
     *
     * @param tag
     * @return
     */
    public Map<String, String> getSettingByTag(String tag) {
        Dictionary params = new Dictionary();
        params.setFieldTag(tag);
        params.setStatus(BaseEnum.StatusEnum.ENABLE.getCode());
        List<Dictionary> entities = dictionaryMapper.select(params);
        return entities.stream().collect(Collectors.toMap(Dictionary::getFieldName, Dictionary::getFieldVal, (k1, k2) -> k1));
    }

    @Transactional(rollbackFor = Throwable.class)
    public void updateFields(List<DictionaryBo> bos) {
        if (bos.isEmpty()) {
            return;
        }
        bos.forEach(bo -> {
            Dictionary entity = new Dictionary();
            BeanUtils.copyProperties(bo, entity);
            if (StringUtils.hasText(entity.getId())) {
                dictionaryMapper.updateByPrimaryKeySelective(entity);
            } else {
                entity.setId(UUIDGenerator.getShortUUID());
                dictionaryMapper.insertSelective(entity);
            }
            if (bo.getStatus() != null) {
                if (bo.getStatus() == BaseEnum.StatusEnum.ENABLE.getCode()) {
                    redisService.getHashOps().put(RedisKey.DICTIONARY_KEY.getKey(entity.getFieldTag()), entity.getFieldName(), entity.getFieldVal());
                } else {
                    redisService.getHashOps().delete(RedisKey.DICTIONARY_KEY.getKey(entity.getFieldTag()), entity.getFieldName());
                }
            }
        });
    }

    public void save(DictionaryBo bo) {
        Dictionary entity = new Dictionary();
        BeanUtils.copyProperties(bo, entity);
        if (StringUtils.hasText(entity.getId())) {
            dictionaryMapper.updateByPrimaryKeySelective(entity);
        } else {
            entity.setId(UUIDGenerator.getShortUUID());
            dictionaryMapper.insertSelective(entity);
        }
        if (bo.getStatus() != null) {
            if (bo.getStatus() == BaseEnum.StatusEnum.ENABLE.getCode()) {
                redisService.getHashOps().put(RedisKey.DICTIONARY_KEY.getKey(entity.getFieldTag()), entity.getFieldName(), entity.getFieldVal());
            } else {
                redisService.getHashOps().delete(RedisKey.DICTIONARY_KEY.getKey(entity.getFieldTag()), entity.getFieldName());
            }
        }
    }

    public void enable(DictionaryBo bo) {
        Dictionary entity = dictionaryMapper.selectByPrimaryKey(bo.getId());
        entity.setStatus(bo.getStatus());
        dictionaryMapper.updateByPrimaryKeySelective(entity);
        if (bo.getStatus() == BaseEnum.StatusEnum.ENABLE.getCode()) {
            redisService.getHashOps().put(RedisKey.DICTIONARY_KEY.getKey(entity.getFieldTag()), entity.getFieldName(), entity.getFieldVal());
        } else {
            redisService.getHashOps().delete(RedisKey.DICTIONARY_KEY.getKey(entity.getFieldTag()), entity.getFieldName());
        }
    }

    public void delete(String id) {
        Dictionary entity = dictionaryMapper.selectByPrimaryKey(id);
        redisService.getHashOps().delete(RedisKey.DICTIONARY_KEY.getKey(entity.getFieldTag()), entity.getFieldName());
        dictionaryMapper.deleteByPrimaryKey(id);
    }
}
